package com.xtm.exercise.utils;

import com.alibaba.fastjson.JSONObject;
import com.sgitg.sgcc.sm.SM4Utils;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class SM4EnDecrypt {
	
//	@Value("${sm2.first.privatekey}")
//	private String firstPrivateKey;
//	
//	@Value("${sm2.first.publickey}")
//	private String firstPublicKey;
//	
//	@Value("${sm2.second.privatekey}")
//	private String secondPrivateKey;
//	
//	@Value("${sm2.second.publickey}")
//	private String secondPublicKey;

	private static String firstPrivateKey = "da63d719917e557df854859be468200e823c21f687a054d0e7ec1548c7954bac";
	
	private static String firstPublicKey = "04ff227ae4113ff5c0ee0a2b2ba31c0f2bb47968f4708c650eaec3d6f6be3ea6104a98ae7e90ad90e5ec35b4d003c44415d3307a6034633549df6d275c51cf7c6c";
	
	private static String secondPrivateKey = "213970b2409dd150038dc5d00f0f23359a001c8f675f3c93ae21243076971e46";
	
	private static String sm4Key = "86C63180C2806ED1F47B859DE501215B";
	
	private static SM4Utils testSM4Utils = new SM4Utils();
	
	static boolean TAGBugExit = false; // 控制程序是否停止 true：遇到错误时停止 false：遇到错误时不停止
	
	static boolean showInf = true; // 控制加解密流程测试时是否显示公私密钥信息 false
	
	
	public static String decryptProcess(String cipherStr) {
		System.out.println("==========SM2 解密开始==========");
		String decryptText = "";
		// 通过生成的私钥进行解密
		try {
//			System.out.println("decryptText：" + cipherStr);
            byte[] decryptByte = testSM4Utils.SG_DecECBData(Hex.decode(sm4Key), Hex.decode(cipherStr));
            decryptText = new String(decryptByte,Charset.forName("UTF-8"));
            
            decryptText = xssEncode(decryptText);
            
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
//		System.out.println("SM2解密成功:"+decryptText);
		System.out.println("==========SM2 解密结束==========");
		
		return decryptText;
	}

	 /** 
     * 将容易引起xss漏洞的半角字符直接替换成全角字符 在保证不删除数据的情况下保存
     * @param s 
     * @return 过滤后的值
     */  
    private static String xssEncode(String value) {  
    	if (value != null) {
            //推荐使用ESAPI库来避免脚本攻击,value = ESAPI.encoder().canonicalize(value);
    		
            // 避免空字符串
//           value = value.replaceAll(" ", "");
            // 避免script 标签
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免src形式的表达式
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 删除单个的 </script> 标签
            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 删除单个的<script ...> 标签
            scriptPattern = Pattern.compile("<script(.*?)>",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 eval(...) 形式表达式
            scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 e­xpression(...) 表达式
            scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 javascript: 表达式
            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 vbscript:表达式
            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // 避免 onload= 表达式
            scriptPattern = Pattern.compile("onload(.*?)=",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            
            value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
            
            value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
     
            value = value.replaceAll("'", "& #39;");
     
            value = value.replaceAll("eval\\((.*)\\)", "");
     
            value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
     
            value = value.replaceAll("script", "");
        }
        return value;
    

    }  
	
	public static String encryptProcess(String plainText) {
		System.out.println("==========SM2 加密开始==========");
		String encrypt = "";
		// 通过生成的私钥进行解密
		try {
//			System.out.println("plainText：" + plainText);
            byte[] encryptByte = testSM4Utils.SG_EncECBData(Hex.decode(sm4Key),plainText.getBytes());
            encrypt = new String(Hex.encode(encryptByte));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
//		System.out.println("SM2加密成功:"+encrypt);
		System.out.println("==========SM2 加密 结束==========");
		
		return encrypt;
	}
	
//	public static JSONObject getParamGetMethod(String tycl_params) throws Exception{
//		
//		if(StringUtils.isNotBlank(tycl_params)){
//			tycl_params = decryptProcess(tycl_params);
//			Map<String, Object> requestQueryParams = new HashMap<String, Object>();
//			String[] params = tycl_params.split("&");
//            for (int i = 0; i < params.length; i++) {
//            	int splitIndex = params[i].indexOf("=");
//                if (splitIndex == -1) {
//                    continue;
//                }
//                String key = params[i].substring(0, splitIndex);
//                if (splitIndex < params[i].length()) {
//                    String value = null;
//                    value = params[i].substring(splitIndex + 1);
//                    if("null".equals(value)) value = "";
//                    requestQueryParams.put(key, value);
//                }
//            }
//            JSONObject json = new JSONObject(requestQueryParams);
//            return json;
//			/*执行方法*/
//		}else{
//			//为空则不执行方法，直接返回值，表示非法
//		}
//		
//		return null;
//	}
	
	public static JSONObject getParamGetMethod(String tycl_params) throws Exception{
		
		if(StringUtils.isNotBlank(tycl_params)){
			tycl_params = decryptProcess(tycl_params);
			Map<String, Object> requestQueryParams = new HashMap<String, Object>();
			String[] params = tycl_params.split("&");
            for (int i = 0; i < params.length; i++) {
            	int splitIndex = params[i].indexOf("=");
                if (splitIndex == -1) {
                    continue;
                }
                String key = params[i].substring(0, splitIndex);
                if (splitIndex < params[i].length()) {
                    String value = null;
                    value = params[i].substring(splitIndex + 1);
//                    if("null".equals(value)) value = "";
                    requestQueryParams.put(key, value);
                }
            }
            JSONObject json = new JSONObject(requestQueryParams);
            return json;
			/*执行方法*/
		}else{
			//为空则不执行方法，直接返回值，表示非法
		}
		
		return null;
	}
	
	
	public static void main(String[] args){
		//验证国密四  sm4 加解密
		String encryptProcess = SM4EnDecrypt.encryptProcess("2020");
		System.out.println(encryptProcess);
		
		String decryptProcess = SM4EnDecrypt.decryptProcess(encryptProcess);
		System.out.println(decryptProcess);
		//get方法-字符串
//		String id = "041b354be472cebbd9f909b0293bac7a55b0d035b2bfd2bbceb09e215ac0a81bad242fe2d4429dd9d6b7826d734a26735483e960fd03c6ac3df61bbc9f613adb64e659d89afdbb18846cd88ef22d887c7ae6b639702dbd6977241e00de415ff45c1e7928f58c260fba8f097442bbb8d2fb";
//		String newId = null;
//		try {
//			newId = (String) decrypt(id,"id","id","get");
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println("===>>> "+newId);
		
		
		
		
		//get方法-实体类
//		MyHome  param = new MyHome();
//		System.out.println("myParam===>>> "+param);
//		
//		String tycl_params = "04198a0354a6900886d3b4c1779fa2416f363bff493c964704a93eeef34aacafab88a0df5c338426f8b8dccba99f761f5e4d5e518cf1cd6e3c35641fe64bc640d8bf749e46b851a4b136ae49f5cd016ba810dd5072ddd6cc1421e1d4a185681dfc2d5b6f72194cf75a9643bb3bf9d6";
//		MyHome myParam = null;
//		try {
//			myParam = (MyHome) decrypt(tycl_params,new MyHome(),new MyHome(),"get");
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println("myParam===>>> "+myParam);
//		
		
		//post方法-字符串
//		String id = "0432f1c6a4e5955acecd1d960e4a2d1311fe7d20f541f667bf7be8a5c6a67766575d752d8597e912351c45a58c34ef21077faacbf862e903195525818a1b8bb5f30f2a0beb0e6f7cf97245b13bea621627a4547c53fbaf82efe183ccc9608fa7a50ac7db678f85";
//		int newId = 0;
//		try {
//			newId =  (Integer) decrypt(id,"id","id","post");
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println("===>>> "+newId);
		
		
		//post方法-实体类
//		MyHome  param = new MyHome();
//		System.out.println("myParam===>>> "+param);
//		
//		String tycl_params = "04f3be5e0b4b96f7f831a2986324ab4a6dcdcd4842e806dfa007bf0bed22aa4b496276f587684f24812d189cad060f4da5bb7090a3dce1e1e2e102edafc32b93e5e8cc7c9b00673c872be86491d956db8affceec868fa1b0f828feb7d2aa9af92c3709ff340ed9fa450c96873790938e9b443b873a030dd0d0c3245298cd77e30363c8f411ff0d301a260d9c78da99a7d430391edec098f2503f028591394a7d21037d8a55325a4503b989e72204fe46c374e27561d5fd77d57eb620ee2c84c803d8c995ee08b1f6c75f24d7e556d41172055e5cc05de2084b9e017a711208c3f6472e0452cb7e2b4bd81f387b49ede4b4f36170a1f0e388d0f37b65fc137d05263ca35aed14d52ad724d9cf95e60bf5fef59ceeba624c672daf5bbd89dcea323a20170f2921a4083ffda4e4defba955be280d4df3fa865dfc9867f76f79";
//		ProcessVo myParam = null;
//		try {
//			Object ob = decrypt(tycl_params,new ProcessVo(),new ProcessVo(),"post");
//			System.out.println("ob===>>> "+ob);
////			myParam = (ProcessVo) decrypt(tycl_params,new ProcessVo(),new ProcessVo(),"post");
//			myParam = (ProcessVo) ob;
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		System.out.println("myParam===>>> "+myParam);
		
//		try {
//			getResponseBody(myParam);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		
		
		//==========验证复杂类型---返回值List<String>
//		List<String> list = new ArrayList<String>();
//		list.add("a");
//		list.add("b");
//		System.out.println(list.toString());
//		System.out.println(new ArrayList<String>() instanceof List);
//		System.out.println("myParam===>>> "+(new ArrayList<String>() instanceof List));
//		try {
//			Map<String, String> map = SM2EnDecrypt.getResponseBody(list);
//			String tycl_params = map.get("tycl_params");
//			System.out.println("tycl_params===>>> "+tycl_params);
//			//list = (List<String>) SM2EnDecrypt.decrypt(tycl_params,new ArrayList<String>(),"post");
//			
			
		//==========验证复杂类型---返回值List<MyHome>
//		List<MyHome> list = new ArrayList<MyHome>();
//		MyHome m1 = new MyHome("黎姿lizi",2,new Date(),new BigDecimal("78789643264.98"));
//		MyHome m2 = new MyHome();
//		list.add(m1);
//		list.add(m2);
//		System.out.println(list.toString());
//		System.out.println(new ArrayList<String>() instanceof List);
//		System.out.println("myParam===>>> "+(new ArrayList<String>() instanceof List));
//		try {
//			Map<String, String> map = SM2EnDecrypt.getResponseBody(list);
//			String tycl_params = map.get("tycl_params");
//			System.out.println("tycl_params===>>> "+tycl_params);
//			//list = (List<String>) SM2EnDecrypt.decrypt(tycl_params,new ArrayList<String>(),"post");
			
			
//		//==========验证复杂类型---返回值List<Map<String,String>>
//		List<Map<String,String>> list = new ArrayList<Map<String,String>>();
//		Map<String,String> m1 = new HashMap<String,String>();
//		m1.put("myName", "liming");
//		m1.put("myMoney", "19737363636");
//		Map<String,String> m2 = new HashMap<String,String>();
//		m2.put("myName", "lizi");
//		m2.put("myMoney", "36236321632");
//		list.add(m1);
//		list.add(m2);
//		System.out.println(list.toString());
//		System.out.println(new ArrayList<Map<String,String>>() instanceof List);
//		System.out.println("myParam===>>> "+(new ArrayList<String>() instanceof List));
//		try {
//			Map<String, String> map = SM2EnDecrypt.getResponseBody(list);
//			String tycl_params = map.get("tycl_params");
//			System.out.println("tycl_params===>>> "+tycl_params);
//			//list = (List<String>) SM2EnDecrypt.decrypt(tycl_params,new ArrayList<String>(),"post");
		
		//==========验证复杂类型---返回值List<Map<String,Object>>
//		List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
//		MyHome my1 = new MyHome("黎姿lizi",2,new Date(),new BigDecimal("78789643264.98"));
//		MyHome my2 = new MyHome();
//		Map<String,Object> m1 = new HashMap<String,Object>();
//		m1.put("myName", my1);
//		Map<String,Object> m2 = new HashMap<String,Object>();
//		m2.put("myMoney", my2);
//		list.add(m1);
//		list.add(m2);
//		System.out.println(list.toString());
//		System.out.println(new ArrayList<Map<String,Object>>() instanceof List);
//		System.out.println("myParam===>>> "+(new ArrayList<Object>() instanceof List));
//		try {
//			Map<String, String> map = SM2EnDecrypt.getResponseBody(list);
//			String tycl_params = map.get("tycl_params");
//			System.out.println("tycl_params===>>> "+tycl_params);
//			//list = (List<String>) SM2EnDecrypt.decrypt(tycl_params,new ArrayList<String>(),"post");
			
			
			
			
			
		//==========验证复杂类型---请求参数---解密---List<String>
//		List<ProcessVo> list = new ArrayList<ProcessVo>();
////		list.add("a");
////		list.add("b");
////		System.out.println("jsonStr===>>> "+JSONObject.toJSONString(list.toString()));
////		System.out.println(new ArrayList<String>() instanceof List);
////		System.out.println("myParam===>>> "+(new ArrayList<String>() instanceof List));
//		try {
//			String tycl_params = "0447730331dee9d21f5c1509ffecf87790de063c8a9615245c845ee07c6777fdf3221b1698e33ddd571e94a9d080b6cf4530f9466214d128748255ed21ee3c685ba874da8d8c75f33a935bd4371702e1b984aa28045e761fe6a6fc22d687f1c9c570fae35765e4b53901e41c37cc83f41c2cd667d4a4768e340b9cd9f5cc7c9f2124afb42c8c3542c29b3a3202e1865e4693346cbd552fa05aa746b2b9c1c10a2dd5c99ac9bc61c9dda854298f166f71286e10780ff803e4feb1cc52723bb82bd654388f621ec7389c9fc73a537f4b4dbb850d4c0ce2b354692ca01de2e72d44ec122fbd0610ab66869e894d2d60185778ef2ea52fcb688bb43c7995ec3621677c4266d929d609c587c6f0c18df819ea05f1b1b1856e39e77089adb7acf8b3939e19b9533173109d75ce3cb38bc0b350620d0c8ccdaac09ecdbafdaa1d245408";
//			
//			list = (List<ProcessVo>) SM2EnDecrypt.decrypt(tycl_params,new ArrayList<ProcessVo>(),new ProcessVo(),"post");
//			System.out.println("tycl_params===>>> "+list.toString());
			
			
			
			
		//==========验证复杂类型---请求参数---解密---List<String>
//		List<Map<String,String>> list = new ArrayList<Map<String,String>>();
//		try {
//			String tycl_params = "0447730331dee9d21f5c1509ffecf87790de063c8a9615245c845ee07c6777fdf3221b1698e33ddd571e94a9d080b6cf4530f9466214d128748255ed21ee3c685ba874da8d8c75f33a935bd4371702e1b984aa28045e761fe6a6fc22d687f1c9c570fae35765e4b53901e41c37cc83f41c2cd667d4a4768e340b9cd9f5cc7c9f2124afb42c8c3542c29b3a3202e1865e4693346cbd552fa05aa746b2b9c1c10a2dd5c99ac9bc61c9dda854298f166f71286e10780ff803e4feb1cc52723bb82bd654388f621ec7389c9fc73a537f4b4dbb850d4c0ce2b354692ca01de2e72d44ec122fbd0610ab66869e894d2d60185778ef2ea52fcb688bb43c7995ec3621677c4266d929d609c587c6f0c18df819ea05f1b1b1856e39e77089adb7acf8b3939e19b9533173109d75ce3cb38bc0b350620d0c8ccdaac09ecdbafdaa1d245408";
//			
//			list = (List<Map<String,String>>) SM2EnDecrypt.decrypt(tycl_params,new ArrayList<Map<String,String>>(),new HashMap<String,String>(),"post");
//			System.out.println("tycl_params===>>> "+list.toString());
//			
			
			
//		String[]  myArray= new String[]{"a","b"};
//		try {
//			String tycl_params = "04476a1b7e5affa86e776624a084a5ce1bb3751aa9598eff2ba94f2d7e350b9f4b06415e4df4517898fc49e1ba47b5fcd980bd9b66a7ae6a6eb1fb5b096d4d7e7913ba1a6f8dda22cea06aa2b70673bc6ba7aa8a7b084e5adb108d477be42916b94b2bc52b476dc5207aec82712a";
//			
//			myArray = SM2EnDecrypt.decryptStrArrayParamPostMethod(tycl_params,new String[]{},"","post");
//			System.out.println("tycl_params===>>> "+myArray);
			
			
			
//		Map<String,Object> map = new HashMap<String,Object>();
////		List<ProcessVo> list = new ArrayList<ProcessVo>();
//	//	list.add("a");
//	//	list.add("b");
//	//	System.out.println("jsonStr===>>> "+JSONObject.toJSONString(list.toString()));
//	//	System.out.println(new ArrayList<String>() instanceof List);
//	//	System.out.println("myParam===>>> "+(new ArrayList<String>() instanceof List));
//	try {
//		String tycl_params = "04dd1cc41ffe4f41015dd3c029af72f43823b503bf78ea6233f4d6838a7eb7f1fb47b81d53898a82ac8d794e4ce371c2feb6109676e94a9447ab93b91d47871dcf611ce216842fe84d73b70f4bcfe6a2de2df0ccafffb774769b78d4382785a8663c35f1e27f7aaace54dd7d835256a230c1f291000f5a182211";
//		
//		map = (Map<String,Object>) SM2EnDecrypt.decrypt(tycl_params,new HashMap<String,Object>(),new HashMap<String,Object>(),"post");
//		System.out.println("tycl_params===>>> "+map);
		
		Map<String,Object> map = new HashMap<String,Object>();
//		List<ProcessVo> list = new ArrayList<ProcessVo>();
	//	list.add("a");
	//	list.add("b");
	//	System.out.println("jsonStr===>>> "+JSONObject.toJSONString(list.toString()));
	//	System.out.println(new ArrayList<String>() instanceof List);
	//	System.out.println("myParam===>>> "+(new ArrayList<String>() instanceof List));
	try {
//		String tycl_params = "04dd1cc41ffe4f41015dd3c029af72f43823b503bf78ea6233f4d6838a7eb7f1fb47b81d53898a82ac8d794e4ce371c2feb6109676e94a9447ab93b91d47871dcf611ce216842fe84d73b70f4bcfe6a2de2df0ccafffb774769b78d4382785a8663c35f1e27f7aaace54dd7d835256a230c1f291000f5a182211";
//		
//		map = (Map<String,Object>) SM2EnDecrypt.decrypt(tycl_params,new HashMap<String,Object>(),new HashMap<String,Object>(),"post");
//		System.out.println("tycl_params===>>> "+map);
		
		
		
//		String e = SM2EnDecrypt.encryptProcess("hello");
//		String d = SM2EnDecrypt.decryptProcess(e);
//		System.out.println("e===>>> "+e);
//		System.out.println("d===>>> "+d);
		
		String e = "043e15bd6fae0a6b4bb5ea81534ab7366bcebf38baa7e1c161aef25a0c97d9540100c45b694b26e6976b6e0457133710d8eb81a56411b15b571ed12c2460c956b30ebb923e7697900c2b399dc2e1b898894093a6e29e6ff1b5b4d5477e2aa336b59dab8b3f73";
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
	
	
	
	
	
	
	}
	
	static class MyHome{
		
		@Override
		public String toString() {
			return "MyHome [name=" + name + ", sex=" + sex + ", birthday="
					+ birthday + ", money=" + money + "]";
		}

		public MyHome(){
			
		}
				
		public MyHome(String name,Integer sex, Date birthday, BigDecimal money){
			this.name = name;
			this.sex = sex;
			this.birthday = birthday;
			this.money = money;
		}
		
		private String name = "黎明liming";
		private Integer sex = 1;
		private Date birthday = new Date();
		private BigDecimal money = new BigDecimal("178900218.98");
		
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public Integer getSex() {
			return sex;
		}
		public void setSex(Integer sex) {
			this.sex = sex;
		}
		public Date getBirthday() {
			return birthday;
		}
		public void setBirthday(Date birthday) {
			this.birthday = birthday;
		}
		public BigDecimal getMoney() {
			return money;
		}
		public void setMoney(BigDecimal money) {
			this.money = money;
		}
		
	}

}
